Unity on WIndowsで/を使ってるのに\パスが紛れ込む原因がわかった話
概要
Unityが扱おうとするパスは/なのに、\が入ってくるケースを殴りたいみたいな話。
Unity EditorでマルチプラットフォームでうごくAssetとか作ってると、パス周りで以下のような事象にあう。
Unity自体はパスをどう扱おうとしてるのか
Unity自体は、MacでもWinでも(自分は試してないけどLinuxでも) ”/“ を返すメソッドが多々ある。
たとえばAssetのパスを得るメソッドは以下のような感じ。
var data = Application.dataPath;
Windows
C:/somewhere/projectPath/Assets
Mac, Linux(たぶん)
/somewhere/projectPath/Assets
Windowsでも/を使っている。
のだけど、たまに\を返してくる、Unityが面倒をみていないメソッドがある。
今回はそれの話。
\を返してくるのは貴様か
Directory.GetFiles メソッドが、すごく特殊で元気な動きをする。
Directory.GetFiles(path)
ものすごく分岐が多い。次のバリエーションを考えてみる。
1. path = “C:/somewhere/”;
2. path = “C:\\somewhere\\”;
3. path = “C:/somewhere”;
4. path = “C:\\somewhere”;
こいつを、Directory.GetFiles メソッドの引数として使うと、その結果は以下のような感じになる。
1
C:/somewhere/a.txt
2
C:\somewhere\a.txt
3
C:/somewhere\a.txt
4
C:\somewhere\a.txt
3が地獄。
・入力パラメータの末尾が/であれば、/を使う
・入力パラメータの末尾が\であれば、\を使う
・入力パラメータの末尾が/や\でなければ、プラットフォームに依存したデリミタを使う
という因果関係があるみたい。アホかやめてくれ。
Q. なぜ問題が出るのか
A. Unity内でファイルを扱う場合、高確率でUnityの定義したメソッドを使う。
それらは/を使ったパスを返してくる。
そこに上述のGetFilesとかを使うと問題がでてくる。
不用意に引数に使ったら即問題が出てくるので、なかなかつらい。
Q. そもそも\を使えばいいのでは?
A. Mac,Win.Linuxを跨ぎたいので却下。\を受け入れられるのはWinだけ、しかもUnityも/を使ったパスを返してくる。
たとえば設定ファイルとかに\を使うと、おめでとう、Jenkinsやらなにやらで一切動かないものが出来上がる。
Windowsでの自動化とかを考えても、Jenkinsが/とか使ってた気がするんでおめでとう感が出てくる。
このメソッドを何の確認もせずに使った上で、Path.Combineとかと組み合わせるとさらなる地獄が出来上がる。
対(殺傷方および)策
対策としては、このメソッド使って得たパスを、必ず “\” -> “/“ へと変えてやることで対処する。
なぜだ。残念すぎる。
もうちょっと言及しておくと、recursiveにフォルダ中のものを返してくるメソッドとかはもっとかわいそうな感じで、
全部\で返してくる。
Directory.GetFiles()はこれでもまだマシな方なのだ。
残念すぎる。